home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / forecastfox___-0.9.7.6-fx.xpi / components / nsForecastfox.js next >
Text File  |  2008-06-03  |  35KB  |  1,080 lines

  1. /*------------------------------------------------------------------------------
  2.   Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
  3.   ----------------------------------------------------------------------------*/
  4.  
  5. /*------------------------------------------------------------------------------
  6.   Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
  7.   ----------------------------------------------------------------------------*/
  8.   
  9. /******************************************************************************
  10.  * WARNING!!! This file cannot be used from the main overlay (forecastfox.js).
  11.  *            There are variables and functions that conflict with browser 
  12.  *            code and could potentially conflict with other extensions.
  13.  *****************************************************************************/ 
  14.  
  15. /******************************************************************************
  16.  * Component Constants
  17.  *****************************************************************************/ 
  18. const Cc = Components.classes;
  19. const Ci = Components.interfaces;
  20. const Cr = Components.results;
  21.  
  22. /******************************************************************************
  23.  * File Permission Constants
  24.  *****************************************************************************/ 
  25. /*jsl:ignore*/
  26. const PERMS_FILE = 0644;
  27. const PERMS_DIRECTORY = 0755;
  28. /*jsl:end*/
  29.  
  30. /******************************************************************************
  31.  * File Type Constants
  32.  *****************************************************************************/
  33. const TYPE_PROFILE = Ci.ffIDiskService.TYPE_PROFILE;
  34. const TYPE_CACHE = Ci.ffIDiskService.TYPE_CACHE;
  35. const TYPE_ICONS = Ci.ffIDiskService.TYPE_ICONS;
  36. const TYPE_TEMP = Ci.ffIDiskService.TYPE_TEMP;
  37. const TYPE_DEFAULTS = Ci.ffIDiskService.TYPE_DEFAULTS;
  38. const TYPE_WEATHERFOX = Ci.ffIDiskService.TYPE_WEATHERFOX;
  39. const TYPE_ERRORS = Ci.ffIDiskService.TYPE_ERRORS;
  40.  
  41. /******************************************************************************
  42.  * Severity Constants
  43.  *****************************************************************************/
  44. const SEVERITY_INFO = Ci.ffIErrorItem.SEVERITY_INFO;
  45. const SEVERITY_WARNING = Ci.ffIErrorItem.SEVERITY_WARNING;
  46. const SEVERITY_ERROR = Ci.ffIErrorItem.SEVERITY_ERROR;
  47.  
  48. /******************************************************************************
  49.  * Preferences Excluded from Profiles Constant
  50.  *****************************************************************************/
  51. const EXCLUDED_PREFS = {
  52.   "migrated": true,
  53.   "migrated.prefs": true,
  54.   "pinged": true,
  55.   "icons.version": true,
  56.   "icons.uninstallfiles": true,
  57.   "profile.current": true,
  58.   "profile.switch.delay": true,
  59.   "profile.switch.enabled": true,      
  60.   "links.alert": true,
  61.   "links.dialog": true,
  62.   "links.panel": true,
  63.   "links.context": true,
  64.   "preview.tooltip.enabled": true
  65. };
  66.  
  67. /******************************************************************************
  68.  * DTD and Namespace Constants for Import, Export, and Profiles.xml
  69.  *****************************************************************************/
  70. const PROFILES_DTD = "http://forecastfox.ensolis.com/specs/1.0/profiles.dtd";
  71. const PROFILES_NS = "http://forecastfox.ensolis.com/specs/1.0/profiles";
  72.  
  73. /******************************************************************************
  74.  * Gets a preference branch.  
  75.  *
  76.  * @param   Boolean if getting the default branch or current branch.
  77.  * @param   Name of the branch to get.  If null is passed then "forecastfox."
  78.  *          is the branch retrieved.
  79.  * @return  Requested preference branch.
  80.  *****************************************************************************/
  81. function getBranch(aDefault, aName)
  82. {
  83.   //forecastf pref branch
  84.   const FF_NAME = "forecastfox.";
  85.   
  86.   //get pref service
  87.   var pbSvc = Cc["@mozilla.org/preferences-service;1"].
  88.               getService(Ci.nsIPrefService);
  89.   
  90.   //get the default branch
  91.   if (aDefault)
  92.     return (aName) ? pbSvc.getDefaultBranch(aName) : 
  93.                      pbSvc.getDefaultBranch(FF_NAME);
  94.   
  95.   //get the specified branch
  96.   return (aName) ? pbSvc.getBranch(aName) : 
  97.                    pbSvc.getBranch(FF_NAME);
  98. }
  99.  
  100. /******************************************************************************
  101.  * Gets a preference.  
  102.  *
  103.  * @param   Name of the preference to retrieve.
  104.  * @return  Requested preference value. 
  105.  *****************************************************************************/
  106. var gHelpersBranch = null;
  107. function getPref(aName)
  108. {
  109.   //get pref branch
  110.   if (!gHelpersBranch)
  111.     gHelpersBranch = getBranch(false, null);
  112.   var branch = gHelpersBranch;
  113.   
  114.   //return value based on pref type
  115.   var rv = "";
  116.   switch (branch.getPrefType(aName)) {
  117.   case Ci.nsIPrefBranch.PREF_INT:
  118.     rv = branch.getIntPref(aName);
  119.     break;
  120.   case Ci.nsIPrefBranch.PREF_BOOL:
  121.     rv = branch.getBoolPref(aName);
  122.     break;
  123.   case Ci.nsIPrefBranch.PREF_STRING:
  124.   default:
  125.     try {
  126.       rv = branch.getComplexValue(aName, Ci.nsIPrefLocalizedString).data;                         
  127.     } catch(e) {
  128.       try {
  129.         rv = branch.getComplexValue(aName, Ci.nsISupportsString).data;
  130.       } catch(e) {
  131.         rv = branch.getCharPref(aName); 
  132.       }
  133.     }
  134.     break;    
  135.   }
  136.   return rv; 
  137. }
  138.  
  139. /******************************************************************************
  140.  * Sets a preference.  
  141.  *
  142.  * @param   Name of the preference to retrieve.
  143.  * @param   Value to set the preference to.
  144.  *****************************************************************************/
  145. function setPref(aName, aValue)
  146. {
  147.   //get pref branch
  148.   if (!gHelpersBranch)
  149.     gHelpersBranch = getBranch(false, null);
  150.   var branch = gHelpersBranch;
  151.   
  152.   //do nothing if value is unchanged
  153.   var oldValue = getPref(aName);
  154.   if (aValue == oldValue)
  155.     return;
  156.   
  157.   //remove user value if same as the default
  158.   var restored = restorePref(aName, aValue);
  159.   if (restored)
  160.     return;
  161.     
  162.   //set value based on pref type
  163.   switch (branch.getPrefType(aName)) {
  164.   case Ci.nsIPrefBranch.PREF_INT:
  165.     branch.setIntPref(aName, aValue);
  166.     break;
  167.   case Ci.nsIPrefBranch.PREF_BOOL:
  168.      branch.setBoolPref(aName, aValue);
  169.      break;
  170.   case Ci.nsIPrefBranch.PREF_STRING:
  171.   default:
  172.     try {
  173.       var plString = Cc["@mozilla.org/pref-localizedstring;1"].
  174.                      createInstance(Ci.nsIPrefLocalizedString);    
  175.       plString.data = aValue;
  176.       branch.setComplexValue(aName, Ci.nsIPrefLocalizedString, plString);
  177.     } catch(e) {
  178.       try {
  179.         var sString = Cc["@mozilla.org/supports-string;1"].
  180.                       createInstance(Ci.nsISupportsString);    
  181.         sString.data = aValue;
  182.         branch.setComplexValue(aName, Ci.nsISupportsString, sString);
  183.       } catch(e) {
  184.         branch.setCharPref(aName, aValue);
  185.       }
  186.     }
  187.     break;                         
  188.   }   
  189. }
  190.  
  191. /******************************************************************************
  192.  * Restores a default preference.  
  193.  *
  194.  * @param   Name of the preference to retrieve.
  195.  * @param   The new value of the preference.
  196.  * @return  True if pref was restored 
  197.  *****************************************************************************/
  198. function restorePref(aName, aValue)
  199. {
  200.   //get pref branch
  201.   var branch = getBranch(true, null);
  202.   
  203.   //get value based on pref type
  204.   try {
  205.     var defaultValue = "";
  206.     switch (branch.getPrefType(aName)) {
  207.     case Ci.nsIPrefBranch.PREF_INT:
  208.       defaultValue = branch.getIntPref(aName);
  209.       break;
  210.     case Ci.nsIPrefBranch.PREF_BOOL:
  211.       defaultValue = branch.getBoolPref(aName);
  212.       break;
  213.     case Ci.nsIPrefBranch.PREF_STRING:
  214.     default:
  215.       try {
  216.         defaultValue = branch.getComplexValue(aName, Ci.nsIPrefLocalizedString).data;                         
  217.       } catch(e) {
  218.         try {
  219.           defaultValue = branch.getComplexValue(aName, Ci.nsISupportsString).data;
  220.         } catch(e) {
  221.           defaultValue = branch.getCharPref(aName); 
  222.         }
  223.       }
  224.       break;    
  225.     }
  226.   } catch(e) {
  227.     return false;
  228.   }
  229.   
  230.   //value is the same do not restore
  231.   if (aValue != defaultValue)
  232.     return false;
  233.   
  234.   //get pref branch
  235.   if (!gHelpersBranch)
  236.     gHelpersBranch = getBranch(false, null);
  237.   branch = gHelpersBranch;
  238.   
  239.   //clear the value
  240.   try {
  241.     branch.clearUserPref(aName); 
  242.   } catch(e) {
  243.     return false;
  244.   }
  245.   
  246.   // preference was cleared
  247.   return true;
  248. }
  249.  
  250. /******************************************************************************
  251.  * removes the specified file
  252.  * 
  253.  * @param     File to remove.  If file is a directory all files within the 
  254.  *            directory will be removed.
  255.  *****************************************************************************/
  256. function removeFile(aFile)
  257. {
  258.   if (aFile.isDirectory())
  259.     aFile.remove(true);
  260.   else
  261.     aFile.remove(false);
  262. }
  263.  
  264. /******************************************************************************
  265.  * Gets a directory based on a special directory key.  
  266.  *
  267.  * @param   Special directory key.
  268.  * @param   Array of sub directories from the special directory.
  269.  * @param   Create the sub directory if it doesn't exist.
  270.  * @return  A nsIFile interface for the requested file.
  271.  *****************************************************************************/
  272. function getKeyedDirectory(aKey, aPathArray, aCreate)
  273. {
  274.   //get directory service
  275.   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
  276.                getService(Ci.nsIProperties);
  277.   
  278.   //get base directory             
  279.   var dir = dirSvc.get(aKey, Ci.nsIFile);
  280.   
  281.   //loop through path array
  282.   for (var i=0; i<aPathArray.length; i++) {      
  283.     dir.append(aPathArray[i]);
  284.     
  285.     //create directory if instructed
  286.     if (aCreate && !dir.exists())
  287.       dir.create(Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
  288.   }
  289.  
  290.   return dir;
  291. }
  292.  
  293. /******************************************************************************
  294.  * Gets a directory from the installed directory.  
  295.  *
  296.  * @param   Array of sub directories from the install directory.
  297.  * @return  A nsIFile interface for the requested file.
  298.  *****************************************************************************/
  299. function getInstallDirectory(aPathArray)
  300. {
  301.   //setup objects
  302.   var dir = null;
  303.   
  304.   //get extension manager - toolkit 1.0 or greater
  305.   if ("@mozilla.org/extensions/manager;1" in Cc) {
  306.     var em = Cc["@mozilla.org/extensions/manager;1"].
  307.              getService(Ci.nsIExtensionManager);
  308.              
  309.     //get install location from extension manager - toolkit 1.5            
  310.     if ("nsIInstallLocation" in Ci) {
  311.       dir = em.getInstallLocation("{0538E3E3-7E9B-4d49-8831-A227C80A7AD3}");
  312.       dir = dir.getItemLocation("{0538E3E3-7E9B-4d49-8831-A227C80A7AD3}");
  313.     }   
  314.   }
  315.     
  316.   //couldn't use extension manager so try the profile directory - non toolkit
  317.   if (!dir) {
  318.     var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
  319.                  getService(Ci.nsIProperties);      
  320.     dir = dirSvc.get("ProfD", Ci.nsIFile);
  321.     dir.append("extensions");
  322.     dir.append("{0538E3E3-7E9B-4d49-8831-A227C80A7AD3}");
  323.     
  324.     //not in the profile directory so it must be in the app directory
  325.     if (!dir.exists()) {
  326.       dir = dirSvc.get("XCurProcD", Ci.nsIFile); 
  327.       dir.append("extensions");
  328.       dir.append("{0538E3E3-7E9B-4d49-8831-A227C80A7AD3}");
  329.     }      
  330.   }
  331.   
  332.   //loop through path array
  333.   for (var i=0; i<aPathArray.length; i++)
  334.     dir.append(aPathArray[i]);
  335.  
  336.   return dir;
  337. }
  338.    
  339. /******************************************************************************
  340.  * Get the top most open window.  A window has to open for this to be called.
  341.  * Use this if the type of window does not matter.
  342.  * 
  343.  * @return  A window object used for modality.
  344.  *****************************************************************************/
  345. function getTopWindow()
  346. {
  347.   //get top window
  348.   var mediator = Cc["@mozilla.org/appshell/window-mediator;1"].
  349.                  getService(Ci.nsIWindowMediator);
  350.   return mediator.getMostRecentWindow(null); 
  351. }
  352.    
  353. /******************************************************************************
  354.  * Get the main application window.  Use this if the type of window does matter.
  355.  * 
  356.  * @return  A window object used for modality.
  357.  *****************************************************************************/
  358. function getMainWindow()
  359. {
  360.   /** this may need to change if main window of a 
  361.       supported app is not "navigator:browser" **/
  362.   
  363.   //get the mediator service
  364.   var mediator = Cc["@mozilla.org/appshell/window-mediator;1"].
  365.                  getService(Ci.nsIWindowMediator);
  366.   
  367.   //get the app window
  368.   var main = mediator.getMostRecentWindow("navigator:browser");
  369.   if (main)
  370.     return main;
  371.                        
  372.   //get the watcher service
  373.   var watcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  374.                 getService(Ci.nsIWindowWatcher);                 
  375.  
  376.   //open a new window    
  377.   main = watcher.openWindow(null, "chrome://browser/content/browser.xul", 
  378.                             "_blank", "chrome,all,dialog=no", "about:blank"); 
  379.   return main;
  380. }
  381.      
  382. /******************************************************************************
  383.  * String enumerator of hash table keys.
  384.  * 
  385.  * @param   Javascript hash table. 
  386.  * @return  A nsIStringEnumerator of the keys.
  387.  *****************************************************************************/
  388. function KeyEnumerator(aHashTable)
  389. {
  390.   //setup key array
  391.   this._keys = [];
  392.   this._index = 0;
  393.   
  394.   //load with data
  395.   if (aHashTable) {
  396.     for (var name in aHashTable)
  397.       this._keys.push(name);
  398.   }
  399. }
  400. KeyEnumerator.prototype = {
  401.   _index: null,
  402.   _keys: null,
  403.   
  404.   QueryInterface: function KeyEnumerator_QueryInterface(aIID)
  405.   {
  406.     if (!aIID.equals(Ci.nsIStringEnumerator) ||
  407.         !aIID.equals(Ci.nsISupports))
  408.       throw Cr.NS_ERROR_NO_INTERFACE; 
  409.     return this;   
  410.   },
  411.   
  412.   hasMore: function KeyEnumerator_hasMore()
  413.   {
  414.     return this._index < this._keys.length;
  415.   },
  416.   
  417.   getNext: function KeyEnumerator_getNext()
  418.   {
  419.     var rv = this._keys[this._index];
  420.     this._index++; 
  421.     return rv;
  422.   }
  423. };
  424.  
  425. /******************************************************************************
  426.  * Sorts an array ascending where the items have a name property. 
  427.  *
  428.  * @param   Current array item.
  429.  * @param   Next array item.
  430.  *
  431.  * @return  1 if greater, 0 if equal, and -1 if less than. 
  432.  *****************************************************************************/
  433. function sortByName(aItem1, aItem2)
  434. {
  435.   if (aItem1.name < aItem2.name)
  436.     return -1;
  437.   else if (aItem1.name == aItem2.name)
  438.     return 0;
  439.  
  440.   return 1;
  441. }
  442.  
  443. /******************************************************************************
  444.  * Get a new prompter.
  445.  *
  446.  * @param   The parent window for the prompter can be null.
  447.  *
  448.  * @return  A new prompter. 
  449.  *****************************************************************************/
  450. function getPrompter(aParent)
  451. {
  452.   //get the watcher service
  453.   var watcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  454.                 getService(Ci.nsIWindowWatcher);
  455.                 
  456.   //return a prompter
  457.   return watcher.getNewPrompter(aParent);
  458. }
  459.  
  460. /******************************************************************************
  461.  * Gets the forecastfox string bundle.
  462.  *
  463.  * @return  A nsIStringBundle interface for the requested url.
  464.  *****************************************************************************/
  465. var gHelpersBundle = null;
  466. function getBundle()
  467. {
  468.   if (gHelpersBundle != null)
  469.     return gHelpersBundle;
  470.     
  471.   const BUNDLE_URL = "chrome://forecastfox/locale/forecastfox.properties";
  472.  
  473.   //get the stringbundle service
  474.   var sbSvc = Cc["@mozilla.org/intl/stringbundle;1"].
  475.               getService(Ci.nsIStringBundleService); 
  476.   
  477.   //get the bundle and return it  
  478.   gHelpersBundle = sbSvc.createBundle(BUNDLE_URL);       
  479.   return gHelpersBundle;
  480. }
  481.  
  482. /******************************************************************************
  483.  * Checks if the alert service is included.
  484.  *
  485.  * @return  True if alert service is present. 
  486.  *****************************************************************************/
  487. var gHelpersHasAlert = null;
  488. function checkAlertService()
  489. {
  490.   //return cached alert check
  491.   if (gHelpersHasAlert != null) 
  492.     return gHelpersHasAlert;
  493.  
  494.   //check if the alert interface exists
  495.   if ("nsIAlertsService" in Ci)
  496.     gHelpersHasAlert = true;
  497.   else
  498.     gHelpersHasAlert = false;
  499.     
  500.   //cache the flag and return the value
  501.   return gHelpersHasAlert;
  502. }
  503.  
  504. /******************************************************************************
  505.  * Open a link in the main application window
  506.  *
  507.  * @param   The url to open.
  508.  * @param   Where to open the link (current, window, tab, tabshifted)
  509.  *****************************************************************************/ 
  510. function openLink(aURL, aWhere)
  511. {
  512.   var win = getMainWindow();
  513.   var browser = win.document.getElementById("content");
  514.   var features = "chrome,all,dialog=no";
  515.   var chrome = "";
  516.   switch (aWhere) {
  517.   
  518.   //open in a new window
  519.   case "window":
  520.     chrome = "chrome://browser/content/browser.xul";    
  521.     win.openDialog(chrome, "_blank", features, aURL, null, null);
  522.     break;
  523.     
  524.   //open in a new tab
  525.   case "tab":
  526.   case "tabshifted":
  527.     var tab = browser.addTab(aURL);
  528.     
  529.     //focus the tab
  530.     if (aWhere == "tab") {
  531.       browser.selectedTab = tab;
  532.       win.content.focus();
  533.     }        
  534.     break;
  535.     
  536.   //open in the current tab
  537.   case "current":
  538.   default: 
  539.     browser.loadURI(aURL);
  540.     win.content.focus();
  541.     break;
  542.   }
  543. }
  544.  
  545. /******************************************************************************
  546.  * Generic item constructor used by different item components as
  547.  * a prototype for the component.
  548.  *
  549.  * @param     Component name.
  550.  ******************************************************************************/
  551. function ItemBase(aName)
  552. {
  553.   this._name = aName;
  554.   this._ifaces = [this.interfaceID, Ci.ffIItem, 
  555.                   Ci.nsIClassInfo, Ci.nsISupports];
  556. }
  557. ItemBase.prototype = {
  558.   _name: null,
  559.   _ifaces: null,
  560.      
  561.   ////////////////////////////////
  562.   // nsISupports
  563.   QueryInterface: function ItemBase_QueryInterface(aIID)
  564.   {
  565.     var ifaces = this.getInterfaces({});
  566.     for (var i=0; i<ifaces.length; i++) {
  567.       if (aIID.equals(ifaces[i]))
  568.         return this;
  569.     }
  570.  
  571.     throw Cr.NS_ERROR_NO_INTERFACE;
  572.   },
  573.             
  574.   ////////////////////////////////
  575.   // nsIClassInfo
  576.   getInterfaces: function ItemBase_getInterfaces(aCount)
  577.   {
  578.     aCount.value = this._ifaces.length;
  579.     return this._ifaces;
  580.   },
  581.   
  582.   getHelperForLanguage: function ItemBase_getHelperForLanguage(aLanguage) { return null; },
  583.   get contractID() { return gComponents[this._name].contractID; },
  584.   get classID() { return gComponents[this._name].classID; },
  585.   get classDescription() { return gComponents[this._name].className; },
  586.   get implementationLanguage() { return Ci.nsIProgrammingLanguage.JAVASCRIPT; },
  587.   get flags() { return Ci.nsIClassInfo.MAIN_THREAD_ONLY; },
  588.             
  589.   ////////////////////////////////
  590.   // ffIItem
  591.     
  592.   /**
  593.    * Unique ID of the item.
  594.    */ 
  595.   get ID() { return this.getProperty("ID"); },
  596.     
  597.   /**
  598.    * String enumerator of property names.
  599.    * 
  600.    */
  601.    get properties() { return new KeyEnumerator(this._properties); },
  602.     
  603.   /**
  604.    * Check if a given property is present in the item.
  605.    * 
  606.    * @param   Name of the property to check.
  607.    * @return  True if present, false if absent.
  608.    */
  609.   hasProperty: function ItemBase_hasProperty(aName)
  610.   {
  611.     return this._properties.hasOwnProperty(aName);
  612.   },
  613.                     
  614.   /**
  615.    * Retrieves a specific property from the item.
  616.    * 
  617.    * @param   Name of the property to retrieve.
  618.    * @return  The value of the property or null if property doesn't exist
  619.    */
  620.   getProperty: function ItemBase_getProperty(aName)
  621.   {
  622.     if (!this.hasProperty(aName))
  623.       return null;
  624.     else
  625.       return this._properties[aName];
  626.   },
  627.   
  628.   /**
  629.    * Sets a specific property for the item.
  630.    * 
  631.    * @param   Name of the property to set.
  632.    * @param   The value to set.
  633.    */
  634.   setProperty: function ItemBase_setProperty(aName, aValue)
  635.   {
  636.     this._properties[aName] = aValue;
  637.   },
  638.   
  639.   /**
  640.    * Removes a property.
  641.    * 
  642.    * @param   Name of property to remove.
  643.    */
  644.   deleteProperty: function ItemBase_deleteProperty(aName)
  645.   {
  646.     //do nothing if property not set
  647.     if (!this.hasProperty(aName))
  648.       return;
  649.     
  650.     //delete the property  
  651.     delete this._properties[aName];  
  652.   },
  653.     
  654.   /**
  655.    * Make a duplicate copy of a item.
  656.    * 
  657.    * @return  A item with the same values as the current item.
  658.    */
  659.   clone: function ItemBase_clone()  
  660.   {
  661.     //create a new item
  662.     var item = Cc[this.contractID].createInstance(this.interfaceID);
  663.                
  664.     //loop through all properties and set on new item
  665.     for (var name in this._properties)
  666.       item.setProperty(name, this._properties[name]);
  667.       
  668.     //return the new item
  669.     return item;             
  670.   },
  671.             
  672.   ////////////////////////////////
  673.   // Internal Functions
  674.   
  675.   /**
  676.    * Helper property to get the main interface.
  677.    */
  678.   get interfaceID() { return gComponents[this._name].interfaceID; }     
  679. };
  680.  
  681. /******************************************************************************
  682.  * Generic service constructor used by different service components as
  683.  * a prototype for the component.
  684.  *
  685.  * @param     Component name.
  686.  ******************************************************************************/
  687. function ServiceBase(aName)
  688. {
  689.   this._name = aName;
  690.   this._ifaces = [this.interfaceID, Ci.ffIService, 
  691.                   Ci.nsIClassInfo, Ci.nsISupports];
  692.   this._bundle = getBundle();  
  693.   this._branch = getBranch(false, null);  
  694. }
  695. ServiceBase.prototype = {
  696.   _name: null,
  697.   _ifaces: null,
  698.   _error: null,
  699.   _bundle: null,
  700.   _branch: null,
  701.      
  702.   ////////////////////////////////
  703.   // nsISupports
  704.   QueryInterface: function ServiceBase_QueryInterface(aIID)
  705.   {
  706.     var ifaces = this.getInterfaces({});
  707.     for (var i=0; i<ifaces.length; i++) {
  708.       if (aIID.equals(ifaces[i]))
  709.         return this;
  710.     }
  711.  
  712.     throw Cr.NS_ERROR_NO_INTERFACE;
  713.   },
  714.             
  715.   ////////////////////////////////
  716.   // nsIClassInfo
  717.   getInterfaces: function ServiceBase_getInterfaces(aCount)
  718.   {
  719.     aCount.value = this._ifaces.length;
  720.     return this._ifaces;
  721.   },
  722.   
  723.   getHelperForLanguage: function ServiceBase_getHelperForLanguage(aLanguage) { return null; },
  724.   get contractID() { return gComponents[this._name].contractID; },
  725.   get classID() { return gComponents[this._name].classID; },
  726.   get classDescription() { return gComponents[this._name].className; },
  727.   get implementationLanguage() { return Ci.nsIProgrammingLanguage.JAVASCRIPT; },
  728.   get flags() { return Ci.nsIClassInfo.SINGLETON; },
  729.             
  730.   ////////////////////////////////
  731.   // ffIService
  732.   
  733.   /**
  734.    * Initialize the component.  Called by the manager service.  Returns false
  735.    * if component could not be loaded.  Chech the lastError property for
  736.    * more information.
  737.    */
  738.   start: function ServiceBase_start() { return true; },
  739.   
  740.   /**
  741.    * Destroy the component.  Called by the manager service.  This may be
  742.    * called prior to start so it needs to be safe.
  743.    */
  744.   stop: function ServiceBase_stop() {},
  745.       
  746.   /**
  747.    * Last error that occurred.
  748.    */
  749.   get lastError() { return this._error; },
  750.   
  751.   /**
  752.    * The default string bundle.
  753.    */
  754.   get bundle() { return this._bundle; },
  755.   
  756.   /**
  757.    * The default user prefernce branch.
  758.    */
  759.   get branch() { return this._branch; },
  760.   
  761.   ////////////////////////////////
  762.   // Internal Functions
  763.   
  764.   /**
  765.    * Helper property to get the main interface.
  766.    */
  767.   get interfaceID() { return gComponents[this._name].interfaceID; }   
  768. };
  769.  
  770. /******************************************************************************
  771.  * Make a component factory used in getClassObject of nsIModule interface.
  772.  *
  773.  * @param   Component constructor.
  774.  * @return  an nsIFactory object.
  775.  *****************************************************************************/  
  776. function makeFactory(aConstructor)
  777. {
  778.   var factory = {
  779.     QueryInterface: function factory_QueryInterface(aIID) 
  780.     {
  781.       if (!aIID.equals(Ci.nsISupports) &&
  782.           !aIID.equals(Ci.nsIFactory))
  783.         throw Cr.NS_ERROR_NO_INTERFACE;
  784.           
  785.       return this;
  786.     },
  787.  
  788.     createInstance: function factory_createInstance(aOuter, aIID) 
  789.     {
  790.       if (aOuter != null)
  791.         throw Cr.NS_ERROR_NO_AGGREGATION;
  792.        
  793.       return (new aConstructor()).QueryInterface(aIID);
  794.     },
  795.     
  796.     lockFactory: function factory_lockFactory(aLock)
  797.     {
  798.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  799.     }
  800.   };
  801.  
  802.   //return the factory object
  803.   return factory;    
  804. }
  805.  
  806. /******************************************************************************
  807.  * Load a components script.
  808.  *
  809.  * @param   URL of the script file to load.
  810.  *****************************************************************************/  
  811. function loadScript(aURL)
  812. {  
  813.   //get script loader
  814.   var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
  815.                getService(Ci.mozIJSSubScriptLoader);
  816.                                    
  817.   //load the script
  818.   loader.loadSubScript(aURL, null);
  819. }
  820.  
  821. /******************************************************************************
  822.  * Registration data
  823.  *****************************************************************************/
  824. var gComponents = {
  825.                        
  826.   ErrorItem: {
  827.     classID: Components.ID("{05B9426A-EC5D-4327-99B9-7926AD8491A1}"),
  828.     className: "Forecastfox Error Item",
  829.     contractID: "@ensolis.com/forecastfox/error-item;1",
  830.     interfaceID: Ci.ffIErrorItem,
  831.     scriptLoaded: false,
  832.     scriptURL: "chrome://forecastfox/content/utilities/error-item.js",
  833.     constructor: "ErrorItem"
  834.   },
  835.   
  836.   DiskService: {
  837.     classID: Components.ID("{4386D2C0-560C-45f9-A55F-413FEE243F3D}"),
  838.     className: "Forecastfox Disk I/O Service",
  839.     contractID: "@ensolis.com/forecastfox/disk-service;1",
  840.     interfaceID: Ci.ffIDiskService, 
  841.     scriptLoaded: false,
  842.     scriptURL: "chrome://forecastfox/content/utilities/disk-service.js",
  843.     constructor: "DiskService"
  844.   },
  845.     
  846.   PingService: {
  847.     classID: Components.ID("{0FF66E5D-62B3-4ed2-BF9B-21FCA2CBD357}"),
  848.     className: "Forecastfox Ping Service",
  849.     contractID: "@ensolis.com/forecastfox/ping-service;1", 
  850.     interfaceID: Ci.ffIPingService, 
  851.     scriptLoaded: false,
  852.     scriptURL: "chrome://forecastfox/content/utilities/ping-service.js",
  853.     constructor: "PingService"
  854.   },
  855.                                
  856.   ResolverItem: {
  857.     classID: Components.ID("{0B770FA3-40C6-4a37-806E-6A47E0FFADAE}"),
  858.     className: "Forecastfox Namespace Resolver Item",
  859.     contractID: "@ensolis.com/forecastfox/resolver-item;1", 
  860.     interfaceID: Ci.nsIDOMXPathNSResolver,
  861.     scriptLoaded: false,
  862.     scriptURL: "chrome://forecastfox/content/parser/resolver-item.js",
  863.     constructor: "ResolverItem"
  864.   },
  865.                       
  866.   ConverterItem: {
  867.     classID: Components.ID("{A8102480-27EA-432a-AC68-5161B3E45CC0}"),
  868.     className: "Forecastfox Converter Item",
  869.     contractID: "@ensolis.com/forecastfox/converter-item;1", 
  870.     interfaceID: Ci.ffIConverterItem,
  871.     scriptLoaded: false,
  872.     scriptURL: "chrome://forecastfox/content/parser/converter-item.js",
  873.     constructor: "ConverterItem"
  874.   },
  875.                    
  876.   ConverterService: {
  877.     classID: Components.ID("{0DEC2682-40DB-4b51-A1E5-085991D800D9}"),
  878.     className: "Forecastfox Converter Service",
  879.     contractID: "@ensolis.com/forecastfox/converter-service;1", 
  880.     interfaceID: Ci.ffIConverterService, 
  881.     scriptLoaded: false,
  882.     scriptURL: "chrome://forecastfox/content/parser/converter-service.js",
  883.     constructor: "ConverterService"
  884.   },
  885.                        
  886.   ParserItem: {
  887.     classID: Components.ID("{FC48D906-4F00-4ee0-A035-DEE0CE5AFB9D}"),
  888.     className: "Forecastfox Parser Item",
  889.     contractID: "@ensolis.com/forecastfox/parser-item;1", 
  890.     interfaceID: Ci.ffIParserItem,
  891.     scriptLoaded: false,
  892.     scriptURL: "chrome://forecastfox/content/parser/parser-item.js",
  893.     constructor: "ParserItem"
  894.   },
  895.                    
  896.   ParserService: {
  897.     classID: Components.ID("{1CE4E984-6F2A-4ac8-BE74-8E47C0F4B445}"),
  898.     className: "Forecastfox Parser Service",
  899.     contractID: "@ensolis.com/forecastfox/parser-service;1", 
  900.     interfaceID: Ci.ffIParserService, 
  901.     scriptLoaded: false,
  902.     scriptURL: "chrome://forecastfox/content/parser/parser-service.js",
  903.     constructor: "ParserService"
  904.   },
  905.   
  906.   ProfileItem: {
  907.     classID: Components.ID("{F41536F9-D435-42fe-A362-32217C972418}"),
  908.     className: "Forecastfox Profile Item",
  909.     contractID: "@ensolis.com/forecastfox/profile-item;1", 
  910.     interfaceID: Ci.ffIProfileItem,
  911.     scriptLoaded: false,
  912.     scriptURL: "chrome://forecastfox/content/profiles/profile-item.js",
  913.     constructor: "ProfileItem"
  914.   },   
  915.                    
  916.   ProfileService: {
  917.     classID: Components.ID("{01F8B6C4-F9E1-4dc8-A980-5A9985CD4111}"),
  918.     className: "Forecastfox Profile Service",
  919.     contractID: "@ensolis.com/forecastfox/profile-service;1", 
  920.     interfaceID: Ci.ffIProfileService, 
  921.     scriptLoaded: false,
  922.     scriptURL: "chrome://forecastfox/content/profiles/profile-service.js",
  923.     constructor: "ProfileService"
  924.   },
  925.                    
  926.   MigratorService: {
  927.     classID: Components.ID("{E938FEBC-166F-498c-A35E-654BB0E2DE7E}"),
  928.     className: "Forecastfox Migrator Service",
  929.     contractID: "@ensolis.com/forecastfox/migrator-service;1", 
  930.     interfaceID: Ci.ffIMigratorService, 
  931.     scriptLoaded: false,
  932.     scriptURL: "chrome://forecastfox/content/profiles/migrator-service.js",
  933.     constructor: "MigratorService"
  934.   },
  935.    
  936.   IconItem: {
  937.     classID: Components.ID("{B1DB225E-C16C-452f-B042-F917732D9C2E}"),
  938.     className: "Forecastfox Icon Item",
  939.     contractID: "@ensolis.com/forecastfox/icon-item;1", 
  940.     interfaceID: Ci.ffIIconItem,
  941.     scriptLoaded: false,
  942.     scriptURL: "chrome://forecastfox/content/icons/icon-item.js",
  943.     constructor: "IconItem"
  944.   },
  945.                        
  946.   PackItem: {
  947.     classID: Components.ID("{0666DE3E-4F11-4e0f-9154-894DAA76CC6E}"),
  948.     className: "Forecastfox Pack Item",
  949.     contractID: "@ensolis.com/forecastfox/pack-item;1",
  950.     interfaceID: Ci.ffIPackItem,
  951.     scriptLoaded: false,
  952.     scriptURL: "chrome://forecastfox/content/icons/pack-item.js",
  953.     constructor: "PackItem"
  954.   },                              
  955.   
  956.   PackService: {
  957.     classID: Components.ID("{0AC191C4-F5C5-4590-B95D-46602B430598}"),
  958.     className: "Forecastfox Icon Pack Service",
  959.     contractID: "@ensolis.com/forecastfox/pack-service;1", 
  960.     interfaceID: Ci.ffIPackService, 
  961.     scriptLoaded: false,
  962.     scriptURL: "chrome://forecastfox/content/icons/pack-service.js",
  963.     constructor: "PackService"
  964.   },
  965.     
  966.   WebService: {
  967.     classID: Components.ID("{9172437D-0D7D-4f86-B3E9-0D57AAFA541C}"),
  968.     className: "Forecastfox Web Service",
  969.     contractID: "@ensolis.com/forecastfox/web-service;1", 
  970.     interfaceID: Ci.ffIWebService, 
  971.     scriptLoaded: false,
  972.     scriptURL: "chrome://forecastfox/content/icons/web-service.js",
  973.     constructor: "WebService",
  974.     category: "JavaScript global property",
  975.     entry: "forecastfox"
  976.   },
  977.                                                              
  978.   ManagerService: {
  979.     classID: Components.ID("{5ADF9E4D-EAA6-4223-853D-D932060094E0}"),
  980.     className: "Forecastfox Manager Service",
  981.     contractID: "@ensolis.com/forecastfox/manager-service;1", 
  982.     interfaceID: Ci.ffIManagerService, 
  983.     scriptLoaded: false,
  984.     scriptURL: "chrome://forecastfox/content/utilities/manager-service.js",
  985.     constructor: "ManagerService"
  986.   }    
  987. };
  988.  
  989. /******************************************************************************
  990.  * Object that implements the nsIModule interface
  991.  *****************************************************************************/
  992. var gModule = {
  993.  
  994.   registerSelf: function gModule_registerSelf(aCompMgr, aFileSpec, aLocation, aType) 
  995.   {      
  996.     //get the component registrar
  997.     var compMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
  998.     
  999.     //get the category manager
  1000.     var catMgr = Cc["@mozilla.org/categorymanager;1"].
  1001.                  getService(Ci.nsICategoryManager);
  1002.                  
  1003.     //loop through components registration data             
  1004.     for (var name in gComponents) {
  1005.       var comp = gComponents[name];
  1006.  
  1007.       //register factory location
  1008.       compMgr.registerFactoryLocation(comp.classID, comp.className, 
  1009.                                       comp.contractID, aFileSpec,
  1010.                                       aLocation, aType); 
  1011.       
  1012.       //register category                                
  1013.       if (comp.hasOwnProperty("category"))
  1014.         catMgr.addCategoryEntry(comp.category, comp.entry, 
  1015.                                 comp.contractID, true, true);                                      
  1016.                                                            
  1017.     }
  1018.   },
  1019.  
  1020.   unregisterSelf: function gModule_unregisterSelf(aCompMgr, aLocation, aType)
  1021.   {
  1022.     //get the component registrar  
  1023.     var compMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
  1024.     
  1025.     //get the category manager
  1026.     var catMgr = Cc["@mozilla.org/categorymanager;1"].
  1027.                  getService(Ci.nsICategoryManager);
  1028.                                       
  1029.     //loop through components registration data             
  1030.     for (var name in gComponents) {
  1031.       var comp = gComponents[name];
  1032.       
  1033.       //unregister factory location
  1034.       compMgr.unregisterFactoryLocation(comp.classID, aLocation);  
  1035.       
  1036.       //unregister category                                
  1037.       if (comp.hasOwnProperty("category"))      
  1038.         catMgr.deleteCategoryEntry(comp.category, comp.entry,
  1039.                                    comp.contractID, true);                                         
  1040.     }        
  1041.   },
  1042.   
  1043.   getClassObject: function gModule_getClassObject(aCompMgr, aCID, aIID) 
  1044.   {
  1045.     //throw if not requesting a factory
  1046.     if (!aIID.equals(Ci.nsIFactory))
  1047.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  1048.       
  1049.     //loop through components registration data             
  1050.     for (var name in gComponents) {
  1051.       var comp = gComponents[name];
  1052.  
  1053.       //component matches  
  1054.       if (aCID.equals(comp.classID)) {
  1055.         
  1056.         //load the script if it isn't loaded
  1057.         if (!comp.scriptLoaded) {
  1058.           loadScript(comp.scriptURL);
  1059.           comp.scriptLoaded = true;
  1060.         }
  1061.             
  1062.         //return factory
  1063.         return makeFactory(eval(comp.constructor));
  1064.       }
  1065.     }
  1066.     
  1067.     //throw if not found
  1068.     throw Cr.NS_ERROR_NO_INTERFACE;
  1069.   },
  1070.  
  1071.   canUnload: function gModule_canUnload(compMgr) { return true; }
  1072. };
  1073.  
  1074. /******************************************************************************
  1075.  * Module entry point
  1076.  *****************************************************************************/
  1077. function NSGetModule(compMgr, fileSpec) 
  1078. {
  1079.   return gModule;
  1080. }